﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using thailandProject.Models;
using thailandProject.ViewModel;
using MvcFilters.Infrastructure.Filters;

namespace thailandProject.Controllers
{
    [ThailandAuthorize(3)]
    public class ClientsController : Controller
    {
        //
        // GET: /Clients/

        /// <summary>
        /// Takes a client's names and searches it against the database. Matches are
        /// returns to the view
        /// </summary>
        /// <param name="clientName">Name of the client</param>
        /// <returns>All clients who have a similar name</returns>
        [HttpPost]
        public ActionResult Index(string clientName)
        {
            try
            {
                ViewBag.Header = "Clients";

                if (Session["searchName"] == null)
                    Session.Add("searchName", clientName.Trim());
                else
                    Session["searchName"] = clientName.Trim();
            }
            catch (Exception ex)
            {
                int errorCode = ErrorLog.logError(ex);
                return RedirectToAction("Error", "Home", new { errorID = errorCode + "" });
            }

            return Index(1, "clientFirstName");
        }

        [HttpGet]
        public ActionResult Index(int? pageNumber, string sortType, bool? removeContextClient = null)
        {
            PagedList<CLIENT> clients = new PagedList<CLIENT>();
            try
            {
                if (removeContextClient.HasValue)
                    Session["ContextClient"] = null;

                //If there's a client in session, go to that client's view page instead
                if (Session["ContextClient"] != null)
                    return RedirectToAction("ViewClient", new { clientId = ((CLIENT)Session["ContextClient"]).clientID });

                if (!pageNumber.HasValue) //First load this will be null
                    return View();

                if (Session["ClientDeleted"] != null)
                    Session["ClientDeleted"] = false;

                ViewBag.Header = "Clients";

                ViewBag.PageNumber = pageNumber == 0 ? (int)Session["pageNumber"] : pageNumber;
                if (Session["pageNumber"] == null)
                    Session.Add("pageNumber", 1);
                else
                    Session["pageNumber"] = pageNumber;

                //If the sort type changes, then update it
                if (!String.IsNullOrEmpty(sortType))
                    ViewBag.SortType = sortType;
                else
                    sortType = ViewBag.SortType;

                string clientName = (string)Session["searchName"];

                clients = ClientSort.getSortedClientList(clientName, sortType, 10, pageNumber.Value);
            }
            catch (Exception ex)
            {
                int errorCode = ErrorLog.logError(ex);
                return RedirectToAction("Error", "Home", new { errorID = errorCode + "" });
            }

            return View(clients);
        }

        [HttpGet]
        [ThailandAuthorize]
        public ActionResult AddClient()
        {
            try
            {
                ViewBag.Header = "Add Client";
                // do not need anything
            }
            catch (Exception ex)
            {
                int errorCode = ErrorLog.logError(ex);
                return RedirectToAction("Error", "Home", new { errorID = errorCode + "" });
            }

            return View();
        }

        [HttpPost]
        [ThailandAuthorize]
        public ActionResult AddClientQuickSearch(string email)
        {
            JsonResult result = Json("false", JsonRequestBehavior.AllowGet);
            try
            {
                ThailandEntities a = new ThailandEntities();

                var clients = from client in a.CLIENTs
                              where client.clientEmail == email &&
                              client.clientIsActive == false
                              select client;

                if (clients.Count() == 1)
                {
                    CLIENT c = clients.ToList()[0];
                    result = Json(ClientToString(c), JsonRequestBehavior.AllowGet);
                }

            }
            catch (Exception ex)
            {
                int errorCode = ErrorLog.logError(ex);
                return RedirectToAction("Error", "Home", new { errorID = errorCode + "" });
            }

            return result;
        }

        private string ClientToString(CLIENT c)
        {
            string rt = "";
            rt += "{" + c.clientID + "}";
            rt += "{" + c.clientFirstName + "}";
            rt += "{" + c.clientLastName + "}";
            rt += "{" + c.clientAddress + "}";
            rt += "{" + c.clientCity + "}";
            rt += "{" + c.clientStateProvidence + "}";
            rt += "{" + c.clientPassportNum + "}";
            rt += "{" + c.clientNotes + "}";

            return rt;
        }

        public ActionResult QuickSearch(string term)
        {
            JsonResult results = new JsonResult();
            try
            {
                ThailandEntities c = new ThailandEntities();

                var clients = c.CLIENTs
                                .Where(r => r.clientIsActive == true &&
                                  (r.clientFirstName.StartsWith(term) ||
                                  r.clientLastName.StartsWith(term)) ||
                                  ((r.clientFirstName + " " + r.clientLastName).StartsWith(term)))
                                .Take(10)
                                .Select(r => new
                                {
                                    label = r.clientFirstName + " " +
                                        (string.IsNullOrEmpty(r.clientLastName) ? "" : r.clientLastName)
                                });
                results = Json(clients, JsonRequestBehavior.AllowGet);
            }
            catch (Exception ex)
            {
                int errorCode = ErrorLog.logError(ex);
                return RedirectToAction("Error", "Home", new { errorID = errorCode + "" });
            }
                            
            return results;
        }

        [HttpPost]
        [ThailandAuthorize]
        public ActionResult AddClient(CLIENT client, string reactivateclient)
        {
            ClientReservation reservation = new ClientReservation();
            try
            {
                ViewBag.Header = "Client Details";

                ThailandEntities c = new ThailandEntities();

                int redirectID = -1;
                if (reactivateclient == "-1")
                {
                    c.CLIENTs.AddObject(client);
                    int change = c.SaveChanges();

                    redirectID = client.clientID;
                }
                else
                {
                    c.ObjectStateManager.ChangeObjectState(client, System.Data.EntityState.Detached); //Detach this so it isn't added
                    //Get this client and reactivate it
                    int clientID = Convert.ToInt32(reactivateclient);
                    var clients = from dclient in c.CLIENTs
                                  where dclient.clientID == clientID
                                  select dclient;
                    CLIENT deactClient = clients.ToList()[0];
                    deactClient.clientIsActive = true;

                    redirectID = deactClient.clientID;

                    int change = c.SaveChanges();
                }
                

                reservation = ClientReservation.getClientDetails(redirectID);
            }
            catch (Exception ex)
            {
                int errorCode = ErrorLog.logError(ex);
                return RedirectToAction("Error", "Home", new { errorID = errorCode + "" });
            }

            // pass back the object and send to ViewClient
            return View("ViewClient", reservation);
        }

        [HttpGet] //Hyperlinks use GET. Forms use POST
        public ActionResult ViewClient(int clientId)
        {
            ClientReservation reservation = new ClientReservation();
            try
            {
                ViewBag.Header = "Client Details";

                reservation = Models.ClientReservation.getClientDetails(clientId);

                //Add this client to Session
                if (Session["ContextClient"] == null)
                    Session.Add("ContextClient", reservation.client);
                else
                    Session["ContextClient"] = reservation.client;

            }
            catch (Exception ex)
            {
                int errorCode = ErrorLog.logError(ex);
                return RedirectToAction("Error", "Home", new { errorID = errorCode + "" });
            }

            return View(reservation); //Get the first and only returned Client
        }

        [HttpGet]
        [ThailandAuthorize]
        public ActionResult ConfirmReservation(int clientId,int resId)
        {
            //Confirms a reservation through the ViewClient page.
            //Sets a Session value to redirect back to the ViewClient page
            try
            {
                if (Session["ViewClientConfirm"] == null)
                    Session.Add("ViewClientConfirm", true);
                else
                    Session["ViewClientConfirm"] = true;
            }
            catch (Exception ex)
            {
                int errorCode = ErrorLog.logError(ex);
                return RedirectToAction("Error", "Home", new { errorID = errorCode + "" });
            }

            return RedirectToAction("AddClientPayment", new { clientId = clientId, resId = resId });
        }

        [HttpGet]
        [ThailandAuthorize]
        public ActionResult DeleteReservation(int resId)
        {
            //Deletes a reservation through the ViewClient page.
            //Returns to the ViewClient page
            int clientID = -1;
            try
            {
                ThailandEntities a = new ThailandEntities();

                var ress = from res in a.RESERVATIONs
                           where res.resID == resId
                           select res;
                RESERVATION delRes = ress.ToList()[0];
                clientID = delRes.clientID;

                //Delete any tasks and payments associated with this reservation
                var tasks = from task in a.TASKs
                            where task.resID == resId
                            select task;
                List<TASK> delTasks = tasks.ToList();

                foreach (TASK t in delTasks)
                    a.DeleteObject(t);

                var payments = from payment in a.PAYMENTs
                               where payment.resID == resId
                               select payment;
                List<PAYMENT> delPay = payments.ToList();

                foreach (PAYMENT p in delPay)
                    a.DeleteObject(p);

                //Finally, delete the reseration
                a.DeleteObject(delRes);

                int change = a.SaveChanges();
            }
            catch (Exception ex)
            {
                int errorCode = ErrorLog.logError(ex);
                return RedirectToAction("Error", "Home", new { errorID = errorCode + "" });
            }

            return RedirectToAction("ViewClient", "Clients", new { clientId = clientID });
        }

        [HttpGet]
        [ThailandAuthorize]
        public ActionResult DeleteClient(int clientId)
        {
            //Deletes the specified client and returns to the index
            try
            {
                Session["ContextClient"] = null; //Remove the context client because we're deleting them
                
                ThailandEntities a = new ThailandEntities();

                var clients = from client in a.CLIENTs
                              where client.clientID == clientId
                              select client;

                CLIENT delClient = clients.ToList()[0];

                #region Old client delete code
                /*/Cascade delete everything that has a tie to this particular client
                var cps = from cp in a.CLIENTPHONEs
                          where cp.clientID == delClient.clientID
                          select cp;
                List<CLIENTPHONE> cPhones = cps.ToList();

                foreach (CLIENTPHONE cp in cPhones)
                    a.DeleteObject(cp);

                //Delete the reservations
                var rs = from r in a.RESERVATIONs
                         where r.clientID == delClient.clientID
                         select r;
                List<RESERVATION> res = rs.ToList();

                foreach (RESERVATION r in res)
                {
                    //Delete the reservation's payments and tasks
                    var ps = from p in a.PAYMENTs
                             where p.resID == r.resID
                             select p;
                    List<PAYMENT> pay = ps.ToList();

                    foreach (PAYMENT p in pay)
                        a.DeleteObject(p);

                    var ts = from t in a.TASKs
                             where t.resID == r.resID
                             select t;
                    List<TASK> task = ts.ToList();

                    foreach (TASK t in task)
                        a.DeleteObject(t);

                    a.DeleteObject(r);
                }

                //Delete the emails sent
                var em = from e in a.EMAILSENTs
                         where e.clientID == delClient.clientID
                         select e;
                List<EMAILSENT> email = em.ToList();

                foreach (EMAILSENT e in email)
                    a.DeleteObject(e);

                //Finally, delete the client
                a.DeleteObject(delClient);*/
                #endregion

                //Deactivate this client
                delClient.clientIsActive = false;

                int change = a.SaveChanges();

                //Notify the page that a client was deleted
                if (Session["ClientDeleted"] == null)
                    Session.Add("ClientDeleted", true);
                else
                    Session["ClientDeleted"] = true;
            }
            catch (Exception ex)
            {
                int errorCode = ErrorLog.logError(ex);
                return RedirectToAction("Error", "Home", new { errorID = errorCode + "" });
            }

            return RedirectToAction("Index");
        }

        [HttpGet]
        [ThailandAuthorize]
        public ActionResult AddClientTask(int clientId, int resId, string clientName)
        {
            // This is a large datatype, is there a better way to do this?
            Pair<Triplet<int, int, string>, List<TASKTYPE>> result = new Pair<Triplet<int, int, string>, List<TASKTYPE>>(
                                                                            new Triplet<int, int, string>(clientId, resId, ""), 
                                                                            new List<TASKTYPE>());

            try
            {
                ViewBag.Header = "Add Task for " + clientName;

                List<TASKTYPE> tasks;
                RESERVATION reservation;
                //Fetch all the TASKTYPES. These will be used in a dropdownlist
                using (ThailandEntities a = new ThailandEntities())
                {
                    //get all task types where the value is not the System Generated one
                    var tasktypes = from tasktype in a.TASKTYPEs
                                    where tasktype.taskTypeID > 0 &&
                                    tasktype.isActive == true
                                    orderby tasktype.taskTypeName
                                    select tasktype;
                    tasks = tasktypes.ToList();

                    var reservations = from res in a.RESERVATIONs
                                       where res.resID == resId
                                       select res;
                    reservation = reservations.ToList()[0];
                    result = new Pair<Triplet<int, int, string>, List<TASKTYPE>>(new Triplet<int, int, string>(clientId, resId, reservation.resStartDate.ToShortDateString()), tasks);
                }
            }
            catch (Exception ex)
            {
                int errorCode = ErrorLog.logError(ex);
                return RedirectToAction("Error", "Home", new { errorID = errorCode + "" });
            }

            //Use a pair object because clientId and resId need to both be passed
            return View(result);
        }

        [HttpPost]
        [ThailandAuthorize]
        public ActionResult AddClientTask(FormCollection data)
        {
            ClientReservation reservation = new ClientReservation();
            try
            {
                ViewBag.Header = "Client Details -- Task Added";

                //Construct a DateTime object based on form input
                DateTime time = Convert.ToDateTime(data["taskDueDate"].ToString()); //By default, the time will be 12:00 AM
                time = time.AddHours(Convert.ToInt32(data["taskTypeHour"].ToString()) + (data["taskTypeMeridian"].ToString() == "PM" ? 12 : 0));
                time = time.AddMinutes(Convert.ToInt32(data["taskTypeMinute"].ToString()));

                //Construct a TASK object based on form input
                TASK newTask = new TASK();
                newTask.taskName = data["taskName"].ToString();
                newTask.taskDueDate = time;
                newTask.taskDetails = data["taskDetails"].ToString();
                newTask.taskTypeID = Convert.ToInt32(data["taskTypeId"].ToString());
                newTask.resID = Convert.ToInt32(data["resId"].ToString());

                //Next, construct the task detail because it has an id reference to newTask
                /*
                TASKDETAIL newDetail = new TASKDETAIL();
                newDetail.taskDetails = data["taskDetail"].ToString();
                newDetail.tdTypeID = 4; //Will always be a user input... hopefully will never change from 4
                newDetail.TASK = newTask;
                */

                using (ThailandEntities a = new ThailandEntities())
                {
                    a.TASKs.AddObject(newTask);
                    int change = a.SaveChanges();
                }
                reservation = ClientReservation.getClientDetails(Convert.ToInt32(data["clientId"].ToString()));
            }
            catch (Exception ex)
            {
                int errorCode = ErrorLog.logError(ex);
                return RedirectToAction("Error", "Home", new { errorID = errorCode + "" });
            }

            return View("ViewClient", reservation);
        }

        [HttpGet]
        [ThailandAuthorize]
        public ActionResult EditClient(int clientId)
        {
            CLIENT editedClient = new CLIENT();
            try
            {
                ViewBag.Header = "Edit Client Information";

                ThailandEntities a = new ThailandEntities();

                var clients = from client in a.CLIENTs
                              where clientId == client.clientID
                              select client;
                editedClient = clients.ToList()[0];
            }
            catch (Exception ex)
            {
                int errorCode = ErrorLog.logError(ex);
                return RedirectToAction("Error", "Home", new { errorID = errorCode + "" });
            }

            return View(editedClient); //Get the first and only returned Client
        }

        [HttpPost]
        [ThailandAuthorize]
        public ActionResult EditClient(CLIENT editedClient)
        {
            ClientReservation reservation = new ClientReservation();
            try
            {
                ViewBag.Header = "Client Details";

                //TODO: Figure out how to bind this to a model
                /*IENT editedClient = new CLIENT();
                editedClient.clientID = Convert.ToInt32(values["clientID"]);
                editedClient.clientFirstName = values["clientFirstName"];
                editedClient.clientLastName = values["clientLastName"];
                editedClient.clientEmail = values["clientEmail"];
                editedClient.clientStateProvidence = values["clientStateProvidence"];
                editedClient.clientNotes = values["clientNotes"];
                editedClient.clientPassportNum = values["clientPassportNum"];
                editedClient.clientAddress = values["clientAddress"];
                editedClient.clientCity = values["clientCity"];
                editedClient.ccISO2 = values["ccISO2"];*/

                ThailandEntities a = new ThailandEntities();

                a.CLIENTs.AddObject(editedClient);
                a.ObjectStateManager.ChangeObjectState(editedClient, System.Data.EntityState.Modified);
                int change = a.SaveChanges(); //Change will be > 0 on success
                
                //Change client's information
                reservation = ClientReservation.getClientDetails(Convert.ToInt32(editedClient.clientID));
            }
            catch (Exception ex)
            {
                int errorCode = ErrorLog.logError(ex);
                return RedirectToAction("Error", "Home", new { errorID = errorCode + "" });
            }

            return View("ViewClient", reservation);
        }

        [HttpGet]
        public ActionResult ViewClientPayments(int clientId)
        {
            // This is a large datatype, is there a better way to do this?
            Pair<Pair<List<PAYMENT>, List<RESERVATION>>, int> result = new Pair<Pair<List<PAYMENT>, List<RESERVATION>>, int>(
                                                                            new Pair<List<PAYMENT>, List<RESERVATION>>(
                                                                                new List<PAYMENT>(),
                                                                                new List<RESERVATION>()), 
                                                                                clientId);

            try
            {
                ViewBag.Header = "View Client Payments";

                DateTime now = DateTime.Now.Date;
                ThailandEntities a = new ThailandEntities();

                //Select all payments that a specific client has made
                var payments = from payment in a.PAYMENTs
                               from reservation in a.RESERVATIONs
                               from client in a.CLIENTs
                               where payment.resID == reservation.resID &&
                               reservation.clientID == client.clientID &&
                               client.clientID == clientId
                               orderby reservation.resStartDate descending
                               select payment;

                var reservations = from reservation in a.RESERVATIONs
                                   where reservation.clientID == clientId &&
                                   reservation.resEndDate >= now
                                   orderby reservation.resEndDate
                                   select reservation;
                result = new Pair<Pair<List<PAYMENT>, List<RESERVATION>>, int>(new Pair<List<PAYMENT>, List<RESERVATION>>(payments.ToList(), reservations.ToList()), clientId);
            }
            catch (Exception ex)
            {
                ErrorLog.logError(ex);
            }

            return View(result);
        }

        [HttpGet]
        [ThailandAuthorize]
        public ActionResult AddClientPayment(int clientId, int resId)
        {
            Triplet<int, int, RESERVATION> result = new Triplet<int, int, RESERVATION>(clientId,resId, null);
            try
            {
                ViewBag.Header = "Client Payment";
                //Get the reservation so the page knows whether to auto-fill
                //certain fields
                ThailandEntities a = new ThailandEntities();
                var ress = from res in a.RESERVATIONs
                                where res.resID == resId
                                select res;
                RESERVATION r = ress.ToList()[0];

                result.value3 = r;
            }
            catch (Exception ex)
            {
                ErrorLog.logError(ex);
            }

            return View(result);
        }

        [HttpPost]
        [ThailandAuthorize]
        public ActionResult AddClientPayment(FormCollection data, string delHeldRes)
        {
            int convertedID = -1;
            try
            {
                bool sendDepositReceived = false;
                bool sendReservationDropped = false;
                List<RESERVATION> olRes = null;
                
                ViewBag.Header = "Client Details";

                PAYMENT newPayment = new PAYMENT();
                newPayment.resID = Convert.ToInt32(data["resId"].ToString());
                newPayment.paymentAmount = Convert.ToDecimal(data["paymentAmount"].ToString());
                newPayment.paymentType = data["paymentType"].ToString();
                newPayment.paymentIsDeposit = Convert.ToBoolean(data["paymentIsDeposit"].ToString());
                newPayment.paymentNotes = data["paymentNotes"].ToString();

                using (ThailandEntities a = new ThailandEntities())
                {
                    a.PAYMENTs.AddObject(newPayment);

                    //In case a deposit was made against a reservation onHold, set this reservation's status to being no longer on hold
                    var reservations = from reservation in a.RESERVATIONs
                                       where reservation.resID == newPayment.resID
                                       select reservation;
                    RESERVATION res = reservations.ToList()[0];

                    if(newPayment.paymentIsDeposit)
                        sendDepositReceived = true;

                    //Only add these tasks if the payment is a deposit and the reservation is being held
                    if (newPayment.paymentIsDeposit && res.resIsHeld)
                    {
                        res.resIsHeld = false;
                        
                        TASK pickup = new TASK();
                        pickup.resID = res.resID;
                        pickup.taskDetails = "Pickup " + res.CLIENT.clientFirstName + (!String.IsNullOrEmpty(res.CLIENT.clientLastName) ?
                            " " + res.CLIENT.clientLastName.Substring(0, 1) + "." : "") + " on " + res.resStartDate.ToShortDateString();
                        pickup.taskDueDate = res.resStartDate;
                        pickup.taskName = "Pickup " + res.CLIENT.clientFirstName + (!String.IsNullOrEmpty(res.CLIENT.clientLastName) ?
                            " " + res.CLIENT.clientLastName.Substring(0, 1) + "." : "");
                        pickup.taskTypeID = 0; //System Generated task

                        TASK dropoff = new TASK();
                        dropoff.resID = res.resID;
                        dropoff.taskDetails = "Dropoff " + res.CLIENT.clientFirstName + (res.CLIENT.clientLastName != null ?
                            " " + res.CLIENT.clientLastName.Substring(0, 1) + "." : "") + " on " + res.resEndDate.ToShortDateString();
                        dropoff.taskDueDate = res.resEndDate;
                        dropoff.taskName = "Dropoff " + res.CLIENT.clientFirstName + (res.CLIENT.clientLastName != null ?
                            " " + res.CLIENT.clientLastName.Substring(0, 1) + "." : "");
                        dropoff.taskTypeID = 0; //System Generated task

                        a.TASKs.AddObject(pickup);
                        a.TASKs.AddObject(dropoff);

                        if (delHeldRes == "true")
                        {
                            //Select any other On Hold reservations that this client owns and delete them
                            var heldRes = from onHoldRes in a.RESERVATIONs
                                          where onHoldRes.resIsHeld == true &&
                                                onHoldRes.clientID == res.clientID
                                          select onHoldRes;
                            olRes = heldRes.ToList(); //overlapping reservations

                            if (olRes.Count > 0)
                                sendReservationDropped = true;
                            //Delete these reservations, because someone beat them
                            foreach (RESERVATION r in olRes)
                            {

                                //Select all associated tasks and delete them
                                var tasks = from task in a.TASKs
                                            where task.resID == r.resID
                                            select task;
                                //Select all associated payments and delete them. There should not be any payments... but just in case
                                var payments = from payment in a.PAYMENTs
                                               where payment.resID == r.resID
                                               select payment;
                                List<TASK> delTasks = tasks.ToList();
                                List<PAYMENT> delPayments = payments.ToList();

                                foreach (TASK t in delTasks)
                                    a.DeleteObject(t);

                                foreach (PAYMENT p in delPayments)
                                    a.DeleteObject(p);

                                //Finally, delete the reservation
                                a.DeleteObject(r);

                                sendReservationDropped = true;
                            }//End to foreach heldres
                        }//End to if delHeldRes == "true"
                    }//End to if new payment is a deposit and the res is held

                    int change = a.SaveChanges();
                }

                convertedID = Convert.ToInt32(data["clientId"]);

                EMAILPREFERENCE pref = EmailController.getPreferences(((USER)Session["user"]).userID);
                if (pref != null && pref.onDeposityMade && sendDepositReceived)
                {
                    //Redirect to the EventEmail controller
                    List<int> clientIDs = new List<int>();
                    clientIDs.Add(newPayment.RESERVATION.clientID);
                    string redirect;

                    if (sendReservationDropped && pref.onReservationDrop) //We need to send reservation dropped emails as well
                    {
                        redirect = "http://" + Request.Url.Authority + "/Clients/SendReservationDroppedRedirect";
                        //Store the affected reservations in session
                        if (Session["DroppedReservations"] == null)
                            Session.Add("DroppedReservations", olRes);
                        else
                            Session["DroppedReservations"] = olRes;
                    }
                    else
                    {
                        if (Session["ViewClientConfirm"] != null)
                        {
                            redirect = (bool)Session["ViewClientConfirm"] ? "http://" + Request.Url.Authority + "/Clients/ViewClient?clientId=" + convertedID :
                                "http://" + Request.Url.Authority + "/Clients/ViewClientPayments?clientId=" + convertedID;
                            Session["ViewClientConfirm"] = false;
                        }
                        else
                            redirect = "http://" + Request.Url.Authority + "/Clients/ViewClientPayments?clientId=" + convertedID;
                    }

                    EmailController.setEventComposeSession(Session, redirect, clientIDs, newPayment, "onDepositMade");
                    return RedirectToAction("EventCompose", "Email");
                }//End to onDepositMade
                else if (pref != null && sendReservationDropped && pref.onReservationDrop)
                {
                    //Load in the information for the onReservationDropped event
                    List<int> clientIDs = new List<int>();

                    foreach (RESERVATION r in olRes.GroupBy(id => id.clientID).Select(rr => rr.First()).ToList())
                        clientIDs.Add(r.clientID);

                    string redirect = "";
                    if (Session["ViewClientConfirm"] != null)
                    {
                        redirect = (bool)Session["ViewClientConfirm"] ? "http://" + Request.Url.Authority + "/Clients/ViewClient?clientId=" + convertedID :
                                "http://" + Request.Url.Authority + "/Clients/ViewClientPayments?clientId=" + convertedID;
                        Session["ViewClientConfirm"] = false;
                    }
                    else
                        redirect = "http://" + Request.Url.Authority + "/Clients/ViewClientPayments?clientId=" + convertedID;

                    EmailController.setEventComposeSession(Session, redirect, clientIDs, olRes, "onReservationDrop");

                    return RedirectToAction("EventCompose", "Email");
                }//End to onReservationDropped
            }
            catch (Exception ex)
            {
                int errorCode = ErrorLog.logError(ex);
                return RedirectToAction("Error", "Home", new { errorID = errorCode + "" });
            }

            bool redirToViewClient = false;
            if (Session["ViewClientConfirm"] != null)
            {
                redirToViewClient = (bool)Session["ViewClientConfirm"];
                Session["ViewClientConfirm"] = false;
            }

            if (redirToViewClient)
                return RedirectToAction("ViewClient", "Clients", new { clientId = convertedID });
            else
                return RedirectToAction("ViewClientPayments", new { clientId = convertedID });
        }

        [HttpGet]
        public ActionResult SendReservationDroppedRedirect()
        {
            try
            {
                //Make sure the olRes session hasn't expired. If it has... oh well
                List<RESERVATION> olRes = (List<RESERVATION>) Session["DroppedReservations"];

                if (olRes != null)
                {
                    //Load in the information for the onReservationDropped event
                    List<int> clientIDs = new List<int>();

                    foreach (RESERVATION r in olRes.GroupBy(id => id.clientID).Select(rr => rr.First()).ToList())
                    {
                        clientIDs.Add(r.clientID);
                    }

                    //Hopefully the session client is still there
                    CLIENT sc = (CLIENT)Session["ContextClient"];
                    string redirect = "";

                    if (Session["ViewClientConfirm"] != null && sc != null)
                    {
                        redirect = (bool)Session["ViewClientConfirm"] ? "http://" + Request.Url.Authority + "/Clients/ViewClient?clientId=" + sc.clientID :
                            "http://" + Request.Url.Authority + "/Clients/ViewClientPayments?clientId=" + sc.clientID;
                        Session["ViewClientConfirm"] = false;
                    }
                    else if(sc != null)
                        redirect = "http://" + Request.Url.Authority + "/Clients/ViewClientPayments?clientId=" + sc.clientID;
                    else
                        redirect = "http://" + Request.Url.Authority;

                    EmailController.setEventComposeSession(Session, redirect, clientIDs, olRes, "onReservationDrop");
                    return RedirectToAction("EventCompose", "Email");
                }
            }
            catch (Exception ex)
            {
                int errorCode = ErrorLog.logError(ex);
                return RedirectToAction("Error", "Home", new { errorID = errorCode + "" });
            }

            return RedirectToAction("Index", "Home");
        }

        [HttpGet]
        public ActionResult ViewClientPayment(int paymentId)
        {
            PAYMENT pay = new PAYMENT();
            try
            {
                ViewBag.Header = "View Client Payment";

                ThailandEntities a = new ThailandEntities();

                var payments = from payment in a.PAYMENTs
                               where payment.paymentID == paymentId
                               select payment;
                pay = payments.ToList()[0];
            }
            catch (Exception ex)
            {
                int errorCode = ErrorLog.logError(ex);
                return RedirectToAction("Error", "Home", new { errorID = errorCode + "" });
            }

            return View(pay);
        }

        [HttpGet]
        [ThailandAuthorize]
        public ActionResult EditClientPayment(int paymentId)
        {
            PAYMENT pay = new PAYMENT();
            try
            {
                ViewBag.Header = "Edit Client Payment";

                ThailandEntities a = new ThailandEntities();

                var payments = from payment in a.PAYMENTs
                               where payment.paymentID == paymentId
                               select payment;
                pay = payments.ToList()[0];
            }
            catch (Exception ex)
            {
                int errorCode = ErrorLog.logError(ex);
                return RedirectToAction("Error", "Home", new { errorID = errorCode + "" });
            }

            return View(pay);
        }

        [HttpPost]
        [ThailandAuthorize]
        public ActionResult EditClientPayment(string btnSubmit, FormCollection data)
        {
            try
            {
                ViewBag.Header = "View Client Payments";

                ThailandEntities a = new ThailandEntities();

                PAYMENT editedPayment = new PAYMENT();
                editedPayment.paymentID = Convert.ToInt32(data["paymentID"]);
                editedPayment.paymentIsDeposit = Convert.ToBoolean(data["paymentIsDeposit"].ToString());
                editedPayment.paymentNotes = data["paymentNotes"].ToString();
                editedPayment.paymentType = data["paymentType"].ToString();
                editedPayment.paymentAmount = Convert.ToDecimal(data["paymentAmount"]);
                editedPayment.resID = Convert.ToInt32(data["resID"]);

                a.PAYMENTs.AddObject(editedPayment);

                //If the "Save" button was pressed
                if (btnSubmit == "Save")
                {
                    a.ObjectStateManager.ChangeObjectState(editedPayment, System.Data.EntityState.Modified);
                    int change = a.SaveChanges(); //Change will be > 0 on success

                    return RedirectToAction("ViewClientPayment", new { paymentId = editedPayment.paymentID });
                }
                else //We are deleting the payment
                {
                    a.ObjectStateManager.ChangeObjectState(editedPayment, System.Data.EntityState.Deleted);
                    int change = a.SaveChanges(); //Change will be > 0 on success

                    //get the reservation info so we can get the clientID
                    var reservations = from reservation in a.RESERVATIONs
                                       where reservation.resID == editedPayment.resID
                                       select reservation;
                    RESERVATION r = reservations.ToList()[0];

                    //See if the user wants to send an email on refund
                    EMAILPREFERENCE pref = EmailController.getPreferences(((USER)Session["user"]).userID);
                    if (pref != null && pref.onRefundMade)
                    {
                        //Redirect to the EventEmail controller
                        List<int> clientIDs = new List<int>();
                        clientIDs.Add(r.clientID);

                        EmailController.setEventComposeSession(Session, "http://" + Request.Url.Authority + "/Clients/ViewClientPayments?clientId=" + r.clientID,
                            clientIDs, editedPayment, "onRefundMade");
                        return RedirectToAction("EventCompose", "Email");
                    }

                    return RedirectToAction("ViewClientPayments", new { clientId = r.clientID });

                }
            }
            catch (Exception ex)
            {
                int errorCode = ErrorLog.logError(ex);
                return RedirectToAction("Error", "Home", new { errorID = errorCode + "" });
            }
        }

        [HttpGet]
        [ThailandAuthorize]
        public ActionResult EditClientReservation(int resId)
        {
            RESERVATION res = new RESERVATION();
            try
            {
                ViewBag.Header = "Edit Client Reservation";

                ThailandEntities a = new ThailandEntities();

                var reservations = from reservation in a.RESERVATIONs
                                   where reservation.resID == resId
                                   select reservation;
                res = reservations.ToList()[0];
            }
            catch (Exception ex)
            {
                int errorCode = ErrorLog.logError(ex);
                return RedirectToAction("Error", "Home", new { errorID = errorCode + "" });
            }

            return View(res);
        }

        [HttpPost]
        [ThailandAuthorize]
        public ActionResult EditClientReservation(string submitBtn, FormCollection data)
        {
            int convertedID = -1;
            RESERVATION copy = new RESERVATION();
            copy.resID = -1;
            try
            {
                ViewBag.Header = "Reservation Details";

                int resId = Convert.ToInt32(data["resId"].ToString());
                ThailandEntities a = new ThailandEntities();
                var reservations = from reservation in a.RESERVATIONs
                                   where reservation.resID == resId
                                   select reservation;


                RESERVATION modRes = reservations.ToList()[0];

                if (submitBtn == "Delete")
                {
                    //Fetch all associated tasks and payments
                    List<PAYMENT> delPayments;
                    List<TASK> delTasks;

                    var payments = from payment in a.PAYMENTs
                                   where payment.resID == modRes.resID
                                   select payment;
                    var tasks = from task in a.TASKs
                                where task.resID == modRes.resID
                                select task;

                    delPayments = payments.ToList();
                    delTasks = tasks.ToList();

                    //Delete all associated payments now
                    foreach (PAYMENT p in delPayments)
                        a.PAYMENTs.DeleteObject(p);
                    foreach (TASK t in delTasks)
                        a.TASKs.DeleteObject(t);

                    //Finally, delete the reservation
                    a.RESERVATIONs.DeleteObject(modRes);

                }
                else
                {
                    copy.resStartDate = modRes.resStartDate;
                    copy.resEndDate = modRes.resEndDate;
                    copy.resQuotedPrice = modRes.resQuotedPrice;
                    copy.resIsHeld = modRes.resIsHeld;
                    copy.PROPERTY = modRes.PROPERTY;
                    copy.resID = modRes.resID;

                    modRes.resDate = modRes.resDate == DateTime.MinValue ? DateTime.Now : modRes.resDate;
                    modRes.resQuotedPrice = Convert.ToDecimal(data["resQuotedPrice"].ToString());
                    modRes.resStartDate = Convert.ToDateTime(data["dateFrom"].ToString());
                    modRes.resEndDate = Convert.ToDateTime(data["dateTo"].ToString());
                    modRes.resIsHeld = Convert.ToBoolean(data["resIsHeld"].ToString());

                    a.ObjectStateManager.ChangeObjectState(copy, System.Data.EntityState.Detached);
                }

                int change = a.SaveChanges();
                convertedID = modRes.clientID;

                EMAILPREFERENCE pref = EmailController.getPreferences(((USER) Session ["user"]).userID);
                if (copy.resID != -1 && pref != null && pref.onReservationEdit)
                {
                  //Redirect to the EventEmail controller
                  List<int> clientIDs = new List<int>();
                  clientIDs.Add(modRes.clientID);

                  List<RESERVATION> res = new List<RESERVATION>();
                  res.Add(copy);
                  res.Add(modRes);

                  EmailController.setEventComposeSession(Session, "http://" + Request.Url.Authority + "/Clients/ViewClient?clientId=" + convertedID,
                      clientIDs, res, "onReservationEdit");
                  return RedirectToAction("EventCompose", "Email");
                }
            }
            catch (Exception ex)
            {
                int errorCode = ErrorLog.logError(ex);
                return RedirectToAction("Error", "Home", new { errorID = errorCode + "" });
            }

            return RedirectToAction("ViewClient", new { clientId = convertedID });
        }

        public ActionResult ShowClients()
        {
            ViewResult theView = new ViewResult();
            try
            {
                ViewBag.Header = "Clients";

                ThailandEntities clients = new ThailandEntities();

                var theseclients = from c in clients.CLIENTs
                                   select c;
                theView = View(theseclients);
            }
            catch (Exception ex)
            {
                int errorCode = ErrorLog.logError(ex);
                return RedirectToAction("Error", "Home", new { errorID = errorCode + "" });
            }

            return theView;
        }

        public ActionResult ViewEmails(int clientId)
        {
            ViewBag.Header = "View Client Emails";

            Pair<List<EMAILSENT>, int> rt = new Pair<List<EMAILSENT>, int>(new List<EMAILSENT>(), clientId);
            try
            {
                ThailandEntities a = new ThailandEntities();

                var emails = from email in a.EMAILSENTs
                             where email.clientID == clientId
                             select email;

                rt.value1 = emails.ToList();
            }
            catch (Exception ex)
            {
                int errorCode = ErrorLog.logError(ex);
                return RedirectToAction("Error", "Home", new { errorID = errorCode + "" });
            }

            return View(rt);
        }

        /// <summary>
        /// Reactivates a client that has been deactivated. If the client is already
        /// active, no change occurs
        /// </summary>
        /// <param name="clientID">client's ID to be reactivated</param>
        [HttpGet]
        [ThailandAuthorize]
        public static void ReactivateClient(int clientID)
        {
            ThailandEntities a = new ThailandEntities();

            var clients = from client in a.CLIENTs
                            where client.clientID == clientID
                            select client;
            CLIENT c;
            if (clients.Count() > 0)
            {
                c = clients.ToList()[0];
                c.clientIsActive = true;

                int change = a.SaveChanges();
            }
        }

        /// <summary>
        /// Removes the current client in Session and returns the current page
        /// </summary>
        public ActionResult RemoveContextClient(string url)
        {
            try
            {
                Session["ContextClient"] = null;

                //If the user was viewing the client, return to the search page
                if (url.Contains("Clients"))
                    return RedirectToAction("Index");
            }
            catch (Exception ex)
            {
                int errorCode = ErrorLog.logError(ex);
                return RedirectToAction("Error", "Home", new { errorID = errorCode + "" });
            }

            return Redirect(url);
        }
    }
}
